package com.lzy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzy.common.BaseStatic;
import com.lzy.entity.Class;
import com.lzy.entity.Student;
import com.lzy.exception.CustomException;
import com.lzy.mapper.StudentMapper;
import com.lzy.service.IClassService;
import com.lzy.service.IStudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzy.vo.StudentWithClassVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2025-04-25
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements IStudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private IClassService aClassService;

    // 修正日志对象初始化
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(StudentServiceImpl.class);

    @Override
    public List<Student> getAll() {
        return studentMapper.getAll();
    }

    @Override
    public IPage getPage(Page<StudentWithClassVO> page, HashMap param) {
        return studentMapper.getPage(page, param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createStudent(Student student) {
        // 1. 基础参数校验
        if (student == null || student.getClassId() == null) {
            throw new CustomException(400, "创建学生失败:参数无效");
        }

        try {
            // 2. 校验学号唯一性
            checkStuNoUnique(student.getStuNo(), null);
            
            // 3. 获取并验证班级
            /**
             * Optional.ofNullable(getClassById(student.getClassId())) 
             * 创建了一个可能包含班级对象或为空的 Optional 容器
             * 
             * .orElseThrow(() -> new CustomException(404, "班级不存在"))
             * 如果 Optional 容器为空，则抛出异常
             * 如果 Optional 容器不为空，则返回班级对象
             */
            Class aClass = Optional.ofNullable(getClassById(student.getClassId()))
                    .orElseThrow(() -> new CustomException(404, "班级不存在"));
            
            // 4. 验证班级人数上限
            if (aClass.getMebers() >= BaseStatic.MAX_MEMBERS) {
                throw new CustomException(400, "班级人数已达上限");
            }
            
            // 5. 设置时间并插入学生信息
            student.setCreateTime(java.time.LocalDateTime.now());
            student.setUpdateTime(java.time.LocalDateTime.now());
            if (studentMapper.insert(student) <= 0) {
                throw new CustomException(500, "插入学生信息失败");
            }
            
            // 6. 更新班级人数
            updateClassMembers(aClass, 1);
            
            return true;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("创建学生异常: {}", e.getMessage(), e);
            throw new CustomException(500, "系统内部错误");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStudent(Student student) {
        // 1. 基础参数校验
        if (student == null || student.getId() == null || student.getClassId() == null) {
            throw new CustomException(400, "更新学生失败:参数无效");
        }

        try {
            // 2. 获取原学生信息
            Student existingStudent = Optional.ofNullable(studentMapper.selectById(student.getId()))
                    .orElseThrow(() -> new CustomException(404, "学生不存在"));
            // 获取旧班级ID
            Integer oldClassId = existingStudent.getClassId();
            // 判断是否需要更新班级
            boolean isClassChanged = !oldClassId.equals(student.getClassId());
            
            // 3. 校验学号唯一性
            checkStuNoUnique(student.getStuNo(), student.getId());
            
            // 4. 只在班级改变时才验证新班级
            if (isClassChanged) {
                // 获取并验证新班级信息
                Class newClass = Optional.ofNullable(getClassById(student.getClassId()))
                        .orElseThrow(() -> new CustomException(404, "新班级不存在"));
                
                // 验证新班级人数上限
                if (newClass.getMebers() >= BaseStatic.MAX_MEMBERS) {
                    throw new CustomException(400, "新班级人数已达上限");
                }
            }
            
            // 5. 更新学生信息
            student.setUpdateTime(java.time.LocalDateTime.now());
            if (studentMapper.updateById(student) <= 0) {
                throw new CustomException(500, "更新学生信息失败");
            }
            
            // 6. 更新班级人数（仅在班级变更时）
            if (isClassChanged) {
                // 新班级人数+1
                updateClassMembers(getClassById(student.getClassId()), 1);
                // 旧班级人数-1
                updateClassMembers(getClassById(oldClassId), -1);
            }
            
            return true;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新学生异常: {}", e.getMessage(), e);
            throw new CustomException(500, "系统内部错误");
        }
    }

    // 学号唯一性校验
    private void checkStuNoUnique(String stuNo, Integer studentId) {
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getStuNo, stuNo)
                .ne(Student::getId, studentId);
        
        if (this.getOne(queryWrapper) != null) {
            throw new CustomException(400, "学号已被使用");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delStudent(Integer id) {
        if (id == null) {
            log.error("删除学生失败:输入参数为空");
            return false;
        }

        try {
            // 查询要删除的学生信息
            Student student = studentMapper.selectById(id);
            if (student == null) {
                log.error("删除学生失败:学生不存在,id={}", id);
                return false;
            }

            // 删除学生信息
            if (studentMapper.deleteById(id) <= 0) {
                log.error("删除学生失败:删除学生信息失败,id={}", id);
                return false;
            }

            // 更新班级人数
            Class aClass = aClassService.getById(student.getClassId());
            if (aClass != null) {
                aClass.setMebers(aClass.getMebers() - 1);
                if (!aClassService.updateById(aClass)) {
                    log.error("删除学生失败:更新班级人数失败,classId={}", aClass.getId());
                    throw new RuntimeException("更新班级人数失败");
                }
            }

            return true;
        } catch (Exception e) {
            log.error("删除学生失败:发生异常,id={}, 异常信息={}", id, e.getMessage(), e);
            throw e; // 触发事务回滚
        }
    }

    // 获取班级信息
    private Class getClassById(Integer classId) {
        return aClassService.getById(classId);
    }

    // 更新班级人数
    private void updateClassMembers(Class clazz, int delta) {
        clazz.setMebers(clazz.getMebers() + delta);
        if (!aClassService.updateById(clazz)) {
            log.error("更新班级人数失败:classId={}", clazz.getId());
            throw new RuntimeException("更新班级人数失败");
        }
    }

}
